package cn.net.autocode.core.utils;

import com.alibaba.fastjson2.JSONObject;
import org.mindrot.jbcrypt.BCrypt;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PasswordUtils {

    // 加密算法
    private static final String ALGORITHM = "AES";
    // 加密模式和填充方式
    private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";

    private static final String generateKey = "sJ73BD09zodxLhGfLXJpXg==";

    private static final String generateIV = "MmsxAyhpE8CLKSZjO/D7xA==";

    //数字
    public static final String REG_NUMBER = "\\d+";
    //字符
    public static final String REG_CHAR = "[A-Z|a-z]+";

    //大写字母
    public static final String REG_UPPERCASE = "[A-Z]+";

    //小写字母
    public static final String REG_LOWERCASE = "[a-z]+";

    //特殊符号
    public static final String REG_SYMBOL = "[~`!@#$%^&*()_\\-+=|<>,.?/:;'\\[\\]{}\"\\\\]+";

    public static JSONObject validate(JSONObject passPolicy, String password){

        //长度校验
        int minlen = passPolicy.getIntValue("pwlen");
        int maxlen = passPolicy.getIntValue("maxLength");
        //最少数字字符限制  minnum
        int minnum = passPolicy.getIntValue("minnum");
        int minchar = passPolicy.getIntValue("minchar");

        int minLower = passPolicy.getIntValue("minLower");
        int minUpper = passPolicy.getIntValue("minUpper");
        int minSpecials = passPolicy.getIntValue("minSpecials");

        //提示信息
        StringBuilder msgBuilder = new StringBuilder();
        if(minlen>0 && minlen>0){
            msgBuilder.append("密码长度要求："+minlen+" ~ "+maxlen+"位");
        }else if(minlen>0){
            msgBuilder.append("密码长度不能小于"+minlen);
        }else if(maxlen>0){
            msgBuilder.append("密码长度不能大于"+maxlen);
        }

        StringBuilder msgBuilder2 = new StringBuilder();

        if(minnum>0){
            msgBuilder2.append("、"+minnum+"位数字");
        }

        if(minchar>0){
            msgBuilder2.append("、"+minchar+"位字母");
        }


        if(minLower>0){
            msgBuilder2.append("、"+minLower+"位小写字母");
        }

        if(minUpper>0){
            msgBuilder2.append("、"+minUpper+"位大写字母");
        }

        if(minSpecials>0){
            msgBuilder2.append("、"+minSpecials+"位特殊字符");
        }
        if (!msgBuilder2.isEmpty()){
            if(!msgBuilder.isEmpty()){
                msgBuilder.append("\n");
            }
            msgBuilder.append("密码中至少包含：").append(msgBuilder2.toString().substring(1));
        }

        //校验规则
        JSONObject rs = new JSONObject();
        rs.put("msg",msgBuilder.toString());
        int length = password.length();
        if(minlen>0 && length<minlen){
            rs.put("code",0);
            return rs;
        }

        if(maxlen>0 && length>maxlen){
            rs.put("code",0);
            return rs;
        }


        if(!PasswordUtils.check(REG_NUMBER,password,minnum)){
            rs.put("code",0);
            return rs;
        }

        //最少字母限制数 minchar
        if(!PasswordUtils.check(REG_CHAR,password,minchar)){
            rs.put("code",0);
            return rs;
        }


        if(!PasswordUtils.check(REG_LOWERCASE,password,minLower)){
            rs.put("code",0);
            return rs;
        }


        if(!PasswordUtils.check(REG_UPPERCASE,password,minUpper)){
            rs.put("code",0);
            return rs;
        }


        if(!PasswordUtils.check(REG_SYMBOL,password,minSpecials)){
            rs.put("code",0);
            return rs;
        }

        rs.put("code",1);
        rs.remove("msg");
        return rs;
    }

    private static boolean check(String reg,String password,int matchCount){
        if(matchCount<=0){
            return true;
        }
        Pattern p = Pattern.compile(reg);
        Matcher m = p.matcher(password); // 获取 matcher 对象
        int count = 0;

        while(m.find()) {
            int start = m.start();
            int end = m.end();
            count=count+end-start;
        }
        return count>=matchCount;
    }
    /**
     * 获取密码的安全等级
     * @param password 密码值
     * @return 密码等级
     */
    public static int passwordLevel(String password) {
        boolean hasUppercase = false;
        boolean hasLowercase = false;
        boolean hasDigit = false;
        boolean hasSpecialChar = false;

        for (char c : password.toCharArray()) {
            if (Character.isUpperCase(c)) {
                hasUppercase = true;
            } else if (Character.isLowerCase(c)) {
                hasLowercase = true;
            } else if (Character.isDigit(c)) {
                hasDigit = true;
            } else if (!Character.isLetterOrDigit(c)) {
                hasSpecialChar = true;
            }
        }

        if (password.length() < 6) {
            return 1; // 密码低于6位，不符合规则
        } else if (password.length() >= 6 && password.length() <= 20) {
            if (hasLowercase && hasDigit) {
                return 2; // 中等安全等级
            } else if ((hasLowercase && hasUppercase) || (hasLowercase && hasSpecialChar) || (hasUppercase && hasDigit)) {
                return 2; // 中等安全等级
            }
            return 1; // 低安全等级
        } else {
            if (hasUppercase && hasLowercase && hasDigit && hasSpecialChar) {
                return 3; // 高安全等级
            } else if ((hasUppercase && hasLowercase && hasDigit) || (hasUppercase && hasLowercase && hasSpecialChar) || (hasLowercase && hasDigit && hasSpecialChar)) {
                return 2; // 中等安全等级
            }
            return 1; // 低安全等级
        }
    }

    /**
     * 密码hash加密
     * @param password 密码明文
     * @return 加密只
     */
    public static String hashpw(String password){
        return BCrypt.hashpw(password,BCrypt.gensalt());
    }

    /**
     * 密码验证
     * @param password 密码明文
     * @param hashed 加密值
     * @return 验证结果
     */
    public static boolean checkpw(String password,String hashed){
        try {
            return BCrypt.checkpw(password,hashed);
        } catch (Exception e) {
            return false;
        }
    }



    /**
     * AES加密
     * @param data 待加密的数据
     * @return 加密后的结果（Base64编码）
     * @throws Exception 可能抛出的异常
     */
    public static String dbPasswordEncrypt(String data) throws Exception {
        // 解码密钥和初始化向量
        byte[] keyBytes = Base64.getDecoder().decode(generateKey);
        byte[] ivBytes = Base64.getDecoder().decode(generateIV);

        // 构建密钥和初始化向量对象
        SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);

        // 初始化加密器
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);

        // 执行加密并返回Base64编码结果
        byte[] encryptedData = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptedData);
    }

    /**
     * AES解密
     * @param encryptedData 加密后的数据（Base64编码）
     * @return 解密后的原始数据
     * @throws Exception 可能抛出的异常
     */
    public static String dbPasswordDecrypt(String encryptedData) throws Exception {
        // 解码密钥、初始化向量和加密数据
        byte[] keyBytes = Base64.getDecoder().decode(generateKey);
        byte[] ivBytes = Base64.getDecoder().decode(generateIV);
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);

        // 构建密钥和初始化向量对象
        SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, ALGORITHM);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);

        // 初始化解密器
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

        // 执行解密并返回结果
        byte[] decryptedData = cipher.doFinal(encryptedBytes);
        return new String(decryptedData, StandardCharsets.UTF_8);
    }


}
